#include <stdio.h>
#include <string.h>
/**
 * CRC-16/DNP   x16+x13+x12+x11+x10+x8+x6+x5+x2+1
 * 是低位在前，高位在后。
 * @see http://www.ip33.com/crc.html
 * @author Yuanqy
 * @Date 2019年7月8日
 * @company http://www.lianyuplus.com/
 */

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long uint64_t;

/**
 * byte转16进制字符后再crc
 */
void byte2hexstr(unsigned char *sSrc, int nSrcLen, char *sDest)
{
    char szTmp[] = "FF";
    for (int i = 0; i < nSrcLen; i++)
    {
        sprintf(szTmp, "%02X", (unsigned char)sSrc[i]);
        strcat(sDest, szTmp);
    }
    return;
}

/******************************************************************************
 * Name:    CRC-16/DNP          x16+x13+x12+x11+x10+x8+x6+x5+x2+1
 * Poly:    0x3D65
 * Init:    0x0000
 * Refin:   True
 * Refout:  True
 * Xorout:  0xFFFF
 * Use:     M-Bus,ect.
 *****************************************************************************/
uint16_t buildCRC16(uint8_t *data, uint32_t length)
{
    //==【改动部分：将byte转为16进制字符后处理】==========
    uint8_t out[length * 2];
    byte2hexstr(data, length, out); //将byte转为16进制字符串
    printf("Ascii :%s\n", out);
    length *= 2;
    //=================================================
    uint8_t index = 0;
    uint16_t crc = 0x0000; // Initial value
    while (length--)
    {
        crc ^= out[index++];
        // crc ^= *data++; // crc ^= *data; data++;
        for (uint8_t i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xA6BC; // 0xA6BC = reverse 0x3D65
            else
                crc = (crc >> 1);
        }
    }
    return crc ^ 0xFFFF; // crc^Xorout
}

int main(int argc, char const *argv[])
{
    // unsigned char buf[] = {0x55, 0x4E, 0x01, 0x01, 0x0C, 0x74, 0xF0, 0xF6, 0x0D, 0xDC, 0xD0, 0xAB, 0xEB, 0xDB, 0xEF, 0x02, 0x14};
    // unsigned char buf[] = {0x55, 0x4E, 0x01, 0x01, 0x0C, 0x74, 0x36, 0xF6, 0x0D, 0xDC, 0x16, 0xAB, 0xEB, 0xDB, 0xEF, 0x9D, 0x7B};
    // unsigned char buf[] = {0x55, 0x4E, 0x01, 0x01, 0x0C, 0x74, 0x4C, 0xF6, 0x0D, 0xDC, 0x6C, 0xAB, 0xEB, 0xDB, 0xEF, 0x47, 0x7A};
    unsigned char buf[] = {0x55, 0x4E, 0x01, 0x01, 0x0C, 0x74, 0x05, 0x32, 0x0D, 0xDC, 0x25, 0x6F, 0xEB, 0xDB, 0xEF, 0x34, 0xEE};
    uint16_t crc = buildCRC16(buf, sizeof buf);
    printf("校验位 :%X", crc); //crc 是低位在前，高位在后。要转换

    return 0;
}
